package com.atguigu.InternetCoding;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

/**
 *Socket类的常用构造器：
 *  public Socket(InetAddress address,int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
 *  public Socket(String host,int port)创建一个流套接字并将其连接到指定主机上的指定端口号。
 *  Socket类的常用方法：
 *  public InputStream getInputStream()返回此套接字的输入流。可以用于接收网络消息
 *  public OutputStream getOutputStream()返回此套接字的输出流。可以用于发送网络消息
 *  public InetAddress getInetAddress()此套接字连接到的远程 IP 地址；如果套接字是未连接的，则返回 null。
 *  public InetAddress getLocalAddress()获取套接字绑定的本地地址。 即本端的IP地址
 *  public int getPort()此套接字连接到的远程端口号；如果尚未连接套接字，则返回 0。
 *  public int getLocalPort()返回此套接字绑定到的本地端口。 如果尚未绑定套接字，则返回 -1。即本端的
 * 端口号。
 *  public void close()关闭此套接字。套接字被关闭后，便不可在以后的网络连接中使用（即无法重新连接
 * 或重新绑定）。需要创建新的套接字对象。 关闭此套接字也将会关闭该套接字的 InputStream 和
 * OutputStream。
 *  public void shutdownInput()如果在套接字上调用 shutdownInput() 后从套接字输入流读取内容，则流将
 * 返回 EOF（文件结束符）。 即不能在从此套接字的输入流中接收任何数据。
 *  public void shutdownOutput()禁用此套接字的输出流。对于 TCP 套接字，任何以前写入的数据都将被发
 * 送，并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流，
 * 则该流将抛出 IOException。 即不能通过此套接字的输出流发送任何数据。
 * 实现TCP编程
 * 例子1：客服端发送信息给服务端，服务端接收
 * @author xiaoqi
 * @data 2021/04/11 16:30
 */
public class TCPDemo {
    //客户端
    @Test
    public void client() {
        ByteArrayOutputStream baos = null;
        InetAddress Inet = null;
        Socket socket = null;
        OutputStream os = null;
        //接收信息
        InputStream is = null;
        try {
            //创建socket对象，Inet对象
            Inet = InetAddress.getLocalHost();
            //Socket(String host, int port),Socket(inet address, int port),需抛出异常
            socket = new Socket(Inet, 8299);
            //写入数据，得到输入流对象
//            os = socket.getOutputStream();
//            //读写，设置编码
//            os.write("你好,这边是客服端,哈哈哈".getBytes(StandardCharsets.UTF_8));
//            //刷新
//            os.flush();
//            //流的末尾,一定要加上，不然不能接受信息，会阻塞
//            socket.shutdownOutput();
            //得到信息
            is = socket.getInputStream();
            int length = 0;
            baos = new ByteArrayOutputStream();
            byte[] by = new byte[5];
            while((length = is.read(by)) != -1){
                baos.write(by, 0, length);
            }
            //输出得到信息
            System.out.println("客服端收到了服务端：" + baos.toString());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    //服务端
    @Test
    public void server() throws IOException {
        while(true){

            //创建ServerSocket, Socket, InputStream，BytesArrayOutputStream对象
            ServerSocket ss = null;
            Socket socket = null;
            InputStream is = null;
            //接收来自服务端的信息
            OutputStream out = null;
            //设置一个写入文件对象
            FileOutputStream fis = null;
            //防止乱码
            ByteArrayOutputStream baos = null;
            try {
                //new object
                fis = new FileOutputStream(new File("E:\\1.txt"));
                //指明端号，开启服务器端口号
                ss = new ServerSocket(8299);
                //监听连接请求
                socket = ss.accept();
                //输入
//            is = socket.getInputStream();
                //输出
                out = socket.getOutputStream();

                //防止出现乱码
//            baos = new ByteArrayOutputStream();
//            byte[] buffer = new byte[5];
//            int length;
//            while ((length = is.read(buffer)) != -1){
//                baos.write(buffer, 0, length);
//                fis.write(buffer);
//            }
//            System.out.println(baos.toString());
//            System.out.println("收到了来自于：" + socket.getInetAddress().getHostName() + "的数据");
                out.write("你好,这边是服务端。".getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭资源
                if(fis != null){
                    fis.close();
                }
                if(baos != null){
                    baos.close();
                }
                if(is != null){
                    is.close();
                }
                if(socket != null){
                    socket.close();
                }
                if(ss != null){
                    ss.close();
                }
            }
        }

    }
    
}
